package com.extremelylargepackage.entity;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import android.graphics.Canvas;
import android.util.Log;

public class Weapon extends Entity
{
	/*** Persistent weapon info ***/
	/**
	 * Projectiles per second
	 */
	protected float _fireRate;
	protected int _damage;
	protected Projectile _projectile;

	/*** Weapon state info ***/
	protected Projectile[] _projectiles;
	protected long _timeSinceLastShot;
	protected Character _owner;
	protected int _idxLastFired;
	protected boolean _enabled;
	
	protected Weapon()
	{
		super();
		_enabled = true;
	}
	
	@Override
	public void updateState(long time) 
	{
		//Update location of owner
		_locX = _owner.getLocX() + (_owner.getWidth() / 2);
		_locY = _owner.getLocY();
		//Update active projectiles, remove dead projectiles.
		for(int i = 0; i < _projectiles.length; ++i)
		{
			Projectile projectile = _projectiles[i];
			projectile.updateState(time);
		}
		_timeSinceLastShot += time;
		//Fire a projectile if enough time has elapsed.
		if(_owner instanceof Player && _status == Status.alive)
		{
			if(_timeSinceLastShot >= (1000/_fireRate))
			{
				fire();
			}
		}
	}
	
	public void fire()
	{
		fire(false, 0, 0);
	}
	
	public void fire(float dx, float dy)
	{
		fire(true, dx, dy);
	}
	
	private void fire(boolean directional, float dx, float dy)
	{
		if(_enabled)
		{
			int nextShot = _idxLastFired + 1;
			if(nextShot >= _projectiles.length)
				nextShot = 0;
			if(_projectiles[nextShot]._status == Status.dead)
			{
				if(!directional)
					_projectiles[nextShot].fire();
				else
					_projectiles[nextShot].fire(dx, dy);
				_timeSinceLastShot = 0;
				_idxLastFired = nextShot;
			}
		}
	}

	public Projectile[] getProjectiles()
	{
		return _projectiles;
	}
	
	private static int MAX_PROJECTILES = 25;
	
	protected void setProjectiles(Projectile proj)
	{
		_idxLastFired = MAX_PROJECTILES;
		_projectile = (Projectile) proj.clone();
		_projectiles = new Projectile[MAX_PROJECTILES];
		for(int i = 0; i < _projectiles.length; i++)
		{
			Projectile copy = (Projectile) proj.clone();
			copy._status = Status.dead;
			copy._owner = this;
			_projectiles[i] = copy;
			//Outside the screen.
			copy._locX = 0;
			copy._locY = -1000;
		}
	}
	
	public boolean canFire()
	{
		return _timeSinceLastShot >= (1000/_fireRate) && _enabled;
	}
	
	public void setWeaponEnabled(boolean enable)
	{
		_enabled = enable;
	}
	
	@Override
	public void onCollision(Entity z) 
	{
		//Do nothing
	}
	
	public boolean hasActiveProjectiles()
	{
		if(_projectiles != null)
		{
			for(int i = 0; i < _projectiles.length; i++)
			{
				if(_projectiles[i]._status != Status.dead)
				{
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public void draw(Canvas c) 
	{
		//TODO Draw weapon when we implement interchangeable parts
		for(Projectile projectile : _projectiles)
		{
			projectile.draw(c);
		}
	}
	
	@Override
	public Object clone()
	{
		//TODO: super.clone()
		Weapon copy = new Weapon();
		setClonedProps(copy);
		return copy;
	}
	
	protected void setClonedProps(Weapon copy)
	{
		copy._name = _name;
		copy._fireRate = _fireRate;
		copy.setProjectiles(_projectile);
	}

	@Override
	public Map<String, Object> getState() {
		Map<String, Object> res = super.getState();

		Set<Map<String, Object>> projectileStates = new HashSet<Map<String, Object>>();
		for(Projectile proj : _projectiles) {
			projectileStates.add(proj.getState());
		}
		res.put("projectile", projectileStates);

		res.put("timeSinceLastShot", String.valueOf(_timeSinceLastShot));
		res.put("idxLastFired", String.valueOf(_idxLastFired));
		res.put("enabled", String.valueOf(_enabled));

		return res;
	}
}
